<?php

require_once('constants.php');

register_shutdown_function('remove_requestfile');

if ($_SERVER["REQUEST_METHOD"] == "POST")
{
    set_time_limit(45);

    session_start();
    if (!isset($_SESSION[FOLDER_NAME_VAR]) && !isset($_SESSION[REQ_FILE_NAME_ARRAY]))
    {
        exit();
    }
    $foldername = $_SESSION[FOLDER_NAME_VAR];
    $respfilename = $foldername . RESP_FILE_NAME;
    $resplockfilename = $foldername . RESP_LOCK_FILE_NAME;
    // Create a unique temp file for storing the request data received by this process
    $reqfilename = tempnam($foldername, "req");
    if (($resplock = fopen($resplockfilename, "r")) === FALSE)
    {
        exit();
    }

    if (($sockinfo = file_get_contents("php://input")) === FALSE)
    {
        exit();
    }
    // Store the name of the new file in session
    $_SESSION[REQ_FILE_NAME_ARRAY][] = $reqfilename;
    session_write_close();

    $hostport_array = extract_info($sockinfo);
    $socket_array = array();
    // Establish the tcp connections to destination servers and create
    // the corrsponding request data files
    foreach ($hostport_array as $id => $hostport)
    {
        if (($sock = stream_socket_client($hostport)) !== FALSE)
        {
            $socket_array[$id] = $sock;
        }
    }
    if (count($socket_array) == 0)
    {
        exit();
    }

    $reqoffset = 0;
    $respdata = '';
    $counter = 0;
    $sleep_time = 250000;
    $finished_flag = RESP_WAITING_TIME / $sleep_time;

    // Loop until all the sockets have terminated or there is no response received
    // within the specified time
    while (count($socket_array) > 0 && $counter < $finished_flag)
    {
        // Read and send the client requests
        if (($reqdata = file_get_contents($reqfilename, false, NULL, $reqoffset)) !== FALSE)
        {
            $req_array = extract_info($reqdata);
            $reqoffset += strlen($reqdata);
        }
        if (count($req_array) > 0)
        {
            // Reset the counter to wait for the responses
            $counter = 0;
            foreach ($req_array as $id => $data)
            {
                if (!array_key_exists($id, $socket_array))
                {
                    continue;
                }
                if (fwrite($socket_array[$id], $data) === FALSE)
                {
                    fclose($socket_array[$id]);
                    unset($socket_array[$id]);
                }
            }
        }

        usleep($sleep_time);

        // Receive the server responses
        $isemptyresp = FALSE;
        // Check if there is at least one response is not empty
        while (!$isemptyresp)
        {
            $isemptyresp = TRUE;
            $receive = $socket_array;
            // A stream resource is also ready on end-of-file, 
            // in which case an fread() will return a zero length string
            if (($num = stream_select($receive, $writearray = NULL, $exceptarray = NULL, 0)) === FALSE)
            {
                break;
            }
            else if ($num == 0)
            {
                break;
            }
            // Combines all the responses
            foreach ($receive as $sock)
            {
                if (($resp = fread($sock, 8192)) !== FALSE)
                {
                    $resplen = strlen($resp);
                    if ($resplen > 0)
                    {
                        $isemptyresp = FALSE;
                        $id = array_search($sock, $socket_array);
                        $respdata = $respdata . $id . SPLIT_SYMBOL . $resplen . SPLIT_SYMBOL . $resp;
                    }
                }
                else
                {
                    fclose($sock);
                    unset($socket_array[$id]);
                }
            }
        }

        // Write the response data into file if it's not empty
        if (!empty($respdata))
        {
            $counter = 0;
            if (flock($resplock, LOCK_SH | LOCK_NB) !== FALSE)
            {
                if (file_put_contents($respfilename, $respdata, FILE_APPEND) !== FALSE)
                {
                    $respdata = '';
                }
                flock($resplock, LOCK_UN);
            }
        }
        else
        {
            $counter++;
        }
    }
}

function extract_info($data)
{
    $lines = explode(SPLIT_SYMBOL, $data);
    $lines_num = count($lines);
    $result = array();

    for ($i = 0; $i < $lines_num - 1; $i+=2)
    {
        $id = $lines[$i];
        if (strlen($id) < MAX_ID && strlen($id) > 0)
        {
            $result[$id] = $lines[$i + 1];
        }
    }
    return $result;
}

function remove_requestfile()
{
    global $reqfilename;
    unlink($reqfilename);
}

?>